#ifndef NETCLIENT_H
#define NETCLIENT_H

#include <QWidget>
#include <QNetworkAccessManager>
#include <QWebSocket>
#include <QProtobufSerializer>
#include <QNetworkReply>
#include "../model/data.h"

namespace model
{
class DataCenter;
}

namespace network
{

class NetClient : public QObject
{
    Q_OBJECT
private:

    const QString HTTP_URL = "http://192.168.157.128:9000";
    const QString WEBSOCKET_URL = "ws://192.168.157.128:9001/ws";

public:
    NetClient(model::DataCenter* const dataCenter);

    //验证网络联通
    void ping();

    //生成请求ID
    QString makeRequestId();

    //发送身份验证消息
    void sendAuth();

    //封装http发送请求的逻辑
    QNetworkReply* sendHttpRequest(const QString& apiPath,const QByteArray& body);

    //封装处理响应的逻辑
    //判断是否有错误，把结果反序列化返回
    //模板函数不能声明与定义分离
    template<class T>
    std::shared_ptr<T> handleHttpResponse(QNetworkReply* httpRep,bool& ok,QString& reason)
    {
        //1.判断http发送的请求过程中是否出错
        if(httpRep->error()!=QNetworkReply::NoError)
        {
            ok = false;
            reason = httpRep->errorString();
            httpRep->deleteLater();
            return std::shared_ptr<T>();
        }
        //2.获取响应的body
        QByteArray repBody =httpRep->readAll();

        //3.针对body反序列化
        std::shared_ptr<T> repObj = std::make_shared<T>();
        repObj->deserialize(&serializer,repBody);

        //4.判定业务处理结果是否正确
        if(!repObj->success())
        {
            ok = false;
            reason=repObj->errmsg();
            httpRep->deleteLater();
            return std::shared_ptr<T>();
        }
        //5.输出结果，释放内存
        ok = true;
        httpRep->deleteLater();
        return repObj;
    }
    //业务功能接口

    //得到用户信息
    void getMyself(const QString& loginSessionId);
    //获得会话列表信息
    void getSessionList(const QString& loginSessionId);
    //获得好友列表消息
    void getFriendList(const QString& loginSessionId);
    //获取好友申请列表消息
    void getApplyList(const QString& loginSessionId);
    //获取最近消息
    void getRecentMessageList(const QString& loginSessionId,const QString& sessionId,bool isUpdateUI);

    //把用户发送的消息发送给服务器
    //extraInfo是扩展信息，在本项目中，只有发送文件消息时表示文件名字，其他待扩展
    void sendMessage(const QString& loginSessionId,const QString& sessionId
    ,model::MessageType msgType,const QByteArray& cont,const QString& extraInfo);
    //修改个人信息的名字
    void changeNickname(const QString& loginSessionId,const QString& nickname);
    //修改个人信息的签名
    void changeDesc(const QString& loginSessionId,const QString& desc);
    //获取验证码
    //登录注册也需要使用这个函数，那时候没有loginSessionId,因此这个函数参数不设置loginSessionId
    void getVertifyCode(const QString& phone);
    //修改手机号
    void changePhone(const QString& loginSessionId,const QString &phone, const QString &verifyCodeId, const QString &verifyCode);
    //修改头像
    void changeAvatar(const QString& loginSessionId,const QByteArray& avatar);
    //删除好友
    void deleteFriend(const QString& loginSessionId,const QString &userId);
    //发送好友申请
    void sendApply(const QString& loginSessionId,const QString &userId);
    //处理好友申请
    void processFriendApply(const QString& loginSessionId,const QString& applyUserId,bool isAgree);
    //处理搜索用户申请
    void sreachUser(const QString& loginSessionId,const QString& key);
    //创建群聊
    void createSession(const QString& loginSessionId,const QList<QString> &memberList);
    //加载群聊好友列表
    void getSessionMemberList(const QString& loginSessionId,const QString& sessionId);
    //根据关键字搜索历史信息
    void getSearchHistoryList(const QString& loginSessionId,const QString& key);
    //根据时间范围搜索历史信息
    void getSearchHistoryListByTime(const QDateTime& beginTime,const QDateTime& endTime,const QString& loginSessionId);
    //使用账号密码登录
    void userLogin(const QString& name,const QString& pswd);
    //使用账号密码注册
    void userRegister(const QString& name,const QString& pswd);
    //使用手机号登录
    void phoneLogin(const QString &phone, const QString &verifyCodeId, const QString &verifyCode);
    //使用手机号注册
    void phoneRegister(const QString &phone, const QString &verifyCodeId, const QString &verifyCode);
    //根据文件Id获取文件
    void getSingleFile(const QString &loginSessionId,const QString &fileId);
    //语音转文字
    void speechConvertText(const QString &loginSessionId,const QString &fileId,const QByteArray& content);

    //下面是Websocket服务器相关的接口

    //初始化websocket
    void initWebSocket();

    void closeWebSocket();

    void handleWSResponse(const zzy_mims::NotifyMessage& notifyNewMessage);
    void handleWSMessage(const model::Message& msg);
    void handleWSApply(const model::UserInfo& userInfo);
    void handleWSProcess(const model::UserInfo& userInfo,bool isAgree);
    void handleWSCreateSession(const model::SessionInfo& sessionInfo);
    //只处理收到消息后的界面展示部分
    void receiveMessage(const QString& sessionId);

private:
    model::DataCenter* dataCenter;

    //http客户端
    QNetworkAccessManager httpClient;

    //websocket 客户端
    QWebSocket websocketClient;

    //序列化器
    QProtobufSerializer serializer;

signals:
};
}//network
#endif // NETCLIENT_H

